package top.bug.blog.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author <a href="https://github.com/jiusi66">九思.</a>
 * @email 10837907@qq.com
 * @from <a href="https://www.52bug.top">递归茶馆-www.52bug.top</a>
 * @description 本地摘要生成工具类
 * 提供多种摘要生成算法：TextRank、位置加权、关键词提取等
 */
@Slf4j
public final class LocalSummaryGenerator {

    /**
     * 中文停用词表
     */
    private static final Set<String> STOP_WORDS = new HashSet<>(Arrays.asList(
            "的", "了", "在", "是", "我", "有", "和", "就", "不", "人", "都", "一", "一个", "上", "也",
            "很", "到", "说", "要", "去", "你", "会", "着", "没有", "看", "好", "自己", "这", "那",
            "他", "她", "它", "我们", "你们", "他们", "这个", "那个", "这些", "那些", "怎么", "什么",
            "为什么", "如何", "因为", "所以", "但是", "虽然", "如果", "然后", "已经", "可以", "应该"));

    /**
     * 句子结束标点
     */
    private static final Pattern SENTENCE_DELIMITER = Pattern.compile("[。！？!?.;]");
    private static final int DEFAULT_SUMMARY_LENGTH = 200;
    /**
     * TextRank阻尼系数
     */
    private static final double DAMPING_FACTOR = 0.85;
    /**
     * TextRank最大迭代次数
     */
    private static final int MAX_ITERATIONS = 20;
    /**
     * 收敛阈值
     */
    private static final double SIMILARITY_THRESHOLD = 1e-6;

    /**
     * 智能生成摘要（自动选择最佳算法）
     *
     * @param content 文章内容
     * @param title   文章标题（可选）
     * @return 生成的摘要
     */
    public static String generateSmartSummary(String content, String title) {
        return generateSmartSummary(content, title, DEFAULT_SUMMARY_LENGTH);
    }

    /**
     * 智能生成摘要（自动选择最佳算法）
     *
     * @param content   文章内容
     * @param title     文章标题（可选）
     * @param maxLength 摘要最大长度
     * @return 生成的摘要
     */
    public static String generateSmartSummary(String content, String title, int maxLength) {
        if (!StringUtils.hasText(content)) {
            return StringUtils.hasText(title) ? title : "";
        }

        try {
            // 根据内容长度选择算法
            if (content.length() < 100) {
                return generateLeadingTextSummary(content, maxLength);
            } else if (content.length() < 500) {
                return generatePositionBasedSummary(content, maxLength);
            } else {
                return generateTextRankSummary(content, title, maxLength);
            }
        } catch (Exception e) {
            log.warn("智能摘要生成失败，使用降级方案", e);
            return generateLeadingTextSummary(content, maxLength);
        }
    }

    /**
     * 基于TextRank算法生成摘要
     *
     * @param content 文章内容
     * @param title   文章标题（可选）
     * @return 生成的摘要
     */
    public static String generateTextRankSummary(String content, String title) {
        return generateTextRankSummary(content, title, DEFAULT_SUMMARY_LENGTH);
    }

    /**
     * 基于TextRank算法生成摘要
     *
     * @param content   文章内容
     * @param title     文章标题（可选）
     * @param maxLength 摘要最大长度
     * @return 生成的摘要
     */
    public static String generateTextRankSummary(String content, String title, int maxLength) {
        long startTime = System.currentTimeMillis();

        try {
            // 1. 文本预处理和句子切分
            List<String> sentences = splitSentences(content);
            if (sentences.isEmpty()) {
                return StringUtils.hasText(title) ? title : "";
            }

            int sentenceCount = sentences.size();
            if (sentenceCount == 1) {
                return truncateSummary(sentences.get(0), maxLength);
            }

            // 2. 构建句子相似度矩阵
            double[][] similarityMatrix = buildSimilarityMatrix(sentences);

            // 3. 使用TextRank算法计算句子权重
            double[] scores = calculateTextRankScores(similarityMatrix);

            // 4. 选择重要句子
            List<SentenceScore> scoredSentences = new ArrayList<>();
            for (int i = 0; i < sentenceCount; i++) {
                scoredSentences.add(new SentenceScore(sentences.get(i), scores[i], i));
            }

            // 按权重降序排序
            scoredSentences.sort((a, b) -> Double.compare(b.score, a.score));

            // 5. 提取摘要并控制长度
            String summary = extractSummaryByLength(scoredSentences, maxLength);

            log.debug("TextRank摘要生成成功，耗时：{}ms", System.currentTimeMillis() - startTime);
            return summary;

        } catch (Exception e) {
            log.error("TextRank摘要生成失败", e);
            return generatePositionBasedSummary(content, maxLength);
        }
    }

    /**
     * 基于句子位置权重的摘要生成
     *
     * @param content   文章内容
     * @param maxLength 摘要最大长度
     * @return 生成的摘要
     */
    public static String generatePositionBasedSummary(String content, int maxLength) {
        List<String> sentences = splitSentences(content);
        if (sentences.isEmpty()) {
            return "";
        }

        // 位置权重：开头和结尾的句子更重要
        List<SentenceScore> scoredSentences = new ArrayList<>();
        int totalSentences = sentences.size();

        for (int i = 0; i < totalSentences; i++) {
            double positionWeight = calculatePositionWeight(i, totalSentences);
            scoredSentences.add(new SentenceScore(sentences.get(i), positionWeight, i));
        }

        // 按原顺序但根据权重选择
        return extractSummaryByLength(
                scoredSentences.stream()
                        .sorted((a, b) -> Double.compare(b.score, a.score))
                        .collect(Collectors.toList()),
                maxLength
        );
    }

    /**
     * 简单的前导文本摘要
     *
     * @param content   文章内容
     * @param maxLength 摘要最大长度
     * @return 生成的摘要
     */
    public static String generateLeadingTextSummary(String content, int maxLength) {
        if (!StringUtils.hasText(content)) {
            return "";
        }

        if (content.length() <= maxLength) {
            return content;
        }

        // 查找合适的截断点（句子结束处）
        String truncated = content.substring(0, Math.min(content.length(), maxLength + 50));
        int lastPunctuation = findLastPunctuation(truncated);

        if (lastPunctuation > maxLength / 2) {
            return truncated.substring(0, lastPunctuation + 1);
        } else {
            return content.substring(0, maxLength) + "...";
        }
    }

    /**
     * 基于关键词频的摘要生成
     *
     * @param content   文章内容
     * @param maxLength 摘要最大长度
     * @return 生成的摘要
     */
    public static String generateKeywordBasedSummary(String content, int maxLength) {
        List<String> sentences = splitSentences(content);
        if (sentences.isEmpty()) {
            return "";
        }

        // 提取关键词并计算句子权重
        Map<String, Integer> wordFrequencies = calculateWordFrequencies(content);
        List<SentenceScore> scoredSentences = new ArrayList<>();

        for (int i = 0; i < sentences.size(); i++) {
            String sentence = sentences.get(i);
            double keywordScore = calculateSentenceKeywordScore(sentence, wordFrequencies);
            double positionWeight = calculatePositionWeight(i, sentences.size());
            double totalScore = 0.6 * keywordScore + 0.4 * positionWeight;

            scoredSentences.add(new SentenceScore(sentence, totalScore, i));
        }

        return extractSummaryByLength(
                scoredSentences.stream()
                        .sorted((a, b) -> Double.compare(b.score, a.score))
                        .collect(Collectors.toList()),
                maxLength
        );
    }

    // ==================== 私有工具方法 ====================

    /**
     * 切分句子
     */
    private static List<String> splitSentences(String text) {
        if (!StringUtils.hasText(text)) {
            return new ArrayList<>();
        }

        String[] rawSentences = SENTENCE_DELIMITER.split(text);
        List<String> sentences = new ArrayList<>();

        for (String sentence : rawSentences) {
            String trimmed = sentence.trim();
            // 过滤过短的句子
            if (trimmed.length() > 5) {
                sentences.add(trimmed);
            }
        }

        return sentences;
    }

    /**
     * 构建句子相似度矩阵
     */
    private static double[][] buildSimilarityMatrix(List<String> sentences) {
        int size = sentences.size();
        double[][] matrix = new double[size][size];

        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (i == j) {
                    // 对角线设为0
                    matrix[i][j] = 0.0;
                } else {
                    matrix[i][j] = calculateSentenceSimilarity(sentences.get(i), sentences.get(j));
                }
            }
        }

        return matrix;
    }

    /**
     * 计算句子相似度（基于词袋模型的Jaccard相似度）
     */
    private static double calculateSentenceSimilarity(String sentence1, String sentence2) {
        Set<String> words1 = segmentSentence(sentence1);
        Set<String> words2 = segmentSentence(sentence2);

        if (words1.isEmpty() || words2.isEmpty()) {
            return 0.0;
        }

        Set<String> intersection = new HashSet<>(words1);
        intersection.retainAll(words2);

        Set<String> union = new HashSet<>(words1);
        union.addAll(words2);

        return union.isEmpty() ? 0.0 : (double) intersection.size() / union.size();
    }

    /**
     * 简单的中文分词
     */
    private static Set<String> segmentSentence(String sentence) {
        // 简易分词：按字符分割，过滤停用词和短词
        return Arrays.stream(sentence.split(""))
                .filter(word -> word.trim().length() > 0)
                .filter(word -> !STOP_WORDS.contains(word))
                // 过滤单字词
                .filter(word -> word.length() > 1)
                .collect(Collectors.toSet());
    }

    /**
     * 计算TextRank分数
     */
    private static double[] calculateTextRankScores(double[][] similarityMatrix) {
        int size = similarityMatrix.length;
        double[] scores = new double[size];
        // 初始分数
        Arrays.fill(scores, 1.0);

        for (int iter = 0; iter < MAX_ITERATIONS; iter++) {
            double[] newScores = new double[size];
            double maxDiff = 0.0;

            for (int i = 0; i < size; i++) {
                double sum = 0.0;
                for (int j = 0; j < size; j++) {
                    if (i != j && similarityMatrix[j][i] > 0) {
                        double denominator = 0.0;
                        for (int k = 0; k < size; k++) {
                            denominator += similarityMatrix[j][k];
                        }
                        sum += similarityMatrix[j][i] / denominator * scores[j];
                    }
                }
                newScores[i] = (1 - DAMPING_FACTOR) + DAMPING_FACTOR * sum;
                maxDiff = Math.max(maxDiff, Math.abs(newScores[i] - scores[i]));
            }

            scores = newScores;
            if (maxDiff < SIMILARITY_THRESHOLD) {
                // 提前收敛
                break;
            }
        }

        return scores;
    }

    /**
     * 计算位置权重
     */
    private static double calculatePositionWeight(int index, int totalSentences) {
        if (totalSentences <= 1) {
            return 1.0;
        }

        // 开头和结尾的句子权重更高
        if (index == 0) {
            // 第一句
            return 1.0;
        }
        if (index == totalSentences - 1) {
            // 最后一句
            return 0.8;
        }
        if (index < 3) {
            // 前三句
            return 0.7;
        }
        if (index > totalSentences - 4) {
            // 后三句
            return 0.6;
        }
        // 越靠前权重越高
        return 0.3 + (0.3 * (totalSentences - index) / totalSentences);
    }

    /**
     * 计算词频
     */
    private static Map<String, Integer> calculateWordFrequencies(String content) {
        Map<String, Integer> frequencies = new HashMap<>();

        Arrays.stream(content.split(""))
                .filter(word -> word.trim().length() > 0)
                .filter(word -> !STOP_WORDS.contains(word))
                .filter(word -> word.length() > 1)
                .forEach(word -> frequencies.put(word, frequencies.getOrDefault(word, 0) + 1));

        return frequencies;
    }

    /**
     * 计算句子关键词得分
     */
    private static double calculateSentenceKeywordScore(String sentence, Map<String, Integer> wordFrequencies) {
        Set<String> words = segmentSentence(sentence);
        if (words.isEmpty()) {
            return 0.0;
        }

        double totalScore = 0.0;
        for (String word : words) {
            totalScore += wordFrequencies.getOrDefault(word, 0);
        }

        return totalScore / words.size();
    }

    /**
     * 根据长度提取摘要
     */
    private static String extractSummaryByLength(List<SentenceScore> scoredSentences, int maxLength) {
        StringBuilder summary = new StringBuilder();
        int currentLength = 0;

        // 按原顺序排序
        List<SentenceScore> sortedByIndex = scoredSentences.stream()
                .sorted(Comparator.comparingInt(s -> s.originalIndex))
                .collect(Collectors.toList());

        for (SentenceScore sentenceScore : sortedByIndex) {
            String sentence = sentenceScore.sentence;
            if (currentLength + sentence.length() <= maxLength) {
                if (summary.length() > 0) {
                    summary.append("。");
                }
                summary.append(sentence);
                currentLength += sentence.length();
            } else {
                // 尝试添加部分句子
                int remainingLength = maxLength - currentLength;
                // 至少保留10个字符
                if (remainingLength > 10) {
                    summary.append("。").append(truncateSentence(sentence, remainingLength - 1));
                }
                break;
            }

            if (currentLength >= maxLength) {
                break;
            }
        }

        return summary.toString();
    }

    /**
     * 截断句子
     */
    private static String truncateSentence(String sentence, int maxLength) {
        if (sentence.length() <= maxLength) {
            return sentence;
        }

        String truncated = sentence.substring(0, maxLength);
        int lastPunctuation = findLastPunctuation(truncated);

        if (lastPunctuation > maxLength / 2) {
            return truncated.substring(0, lastPunctuation + 1);
        } else {
            return truncated + "...";
        }
    }

    /**
     * 查找最后一个标点符号
     */
    private static int findLastPunctuation(String text) {
        int lastPunctuation = -1;
        for (int i = text.length() - 1; i >= 0; i--) {
            char c = text.charAt(i);
            if (c == '。' || c == '！' || c == '？' || c == '.' || c == '!' || c == '?') {
                lastPunctuation = i;
                break;
            }
        }
        return lastPunctuation;
    }

    private static String truncateSummary(String text, int maxLength) {
        if (text.length() <= maxLength) {
            return text;
        }
        return text.substring(0, maxLength) + "...";
    }

    /**
     * 句子评分封装类
     */
    private static class SentenceScore {
        final String sentence;
        final double score;
        final int originalIndex;

        SentenceScore(String sentence, double score, int originalIndex) {
            this.sentence = sentence;
            this.score = score;
            this.originalIndex = originalIndex;
        }
    }
}